package com.dazhi.boot.context.event;

import com.dazhi.boot.ConfigurableBootstrapContext;
import com.dazhi.boot.SpringApplication;
import com.dazhi.boot.SpringApplicationRunListener;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.ConfigurableEnvironment;

import java.time.Duration;

public class EventPublishingRunListener implements SpringApplicationRunListener {
    private final SpringApplication application;
    private final String[] args;
    // 把这些消息广播出去 springframework里的一个类
    private final SimpleApplicationEventMulticaster initialMulticaster;
    EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
    }
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        multicastInitialEvent(new ApplicationStartingEvent(bootstrapContext,this.application, this.args));
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        multicastInitialEvent(new ApplicationEnvironmentPreparedEvent(bootstrapContext,this.application,this.args,environment));
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        multicastInitialEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        for (ApplicationListener<?> listener : this.application.getListeners()) {
            if (listener instanceof ApplicationContextAware contextAware) {
                contextAware.setApplicationContext(context);
            }
            context.addApplicationListener(listener);
        }
        multicastInitialEvent(new ApplicationPreparedEvent(this.application, this.args, context));
    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        context.publishEvent(new ApplicationStartedEvent(this.application,this.args,context));
    }

    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        SpringApplicationRunListener.super.failed(context, exception);
    }

    private void multicastInitialEvent(ApplicationEvent event) {
        // 刷新监听器，每次都刷新，不知道为啥
        application.getListeners().forEach(this.initialMulticaster::addApplicationListener);
        initialMulticaster.multicastEvent(event);
    }
}
